package b.gate.to.juhe

import java.lang.reflect.{ParameterizedType, Type => JavaType}

import b.gate.pcks.{SerializerUtils, T报文适配器}
import b.gate.utils.CC系统内部错

import scala.collection.mutable.ListBuffer

/**
  * 长亮公司LTTS报文格式适配。
  *
  * 贲国称 于 16/9/7 创建。
  */
object O长亮报文适配器 extends T报文适配器 {
  private val v字典 = Map[String, String]( // 第三方对平台的名字映射
    "机构号" -> "brc",
    "柜员号" -> "usr",
    "时间" -> "time",
    "流水号" -> "seqno",
    "明细" -> "details"
  )
  private def f提取变量值(v类型: Class[_], v名值对s: Map[String, String], v变量名: String): Option[Any] = {
    val v第三方名字 = v字典.getOrElse(v变量名.drop(1), v变量名.drop(1)) // throw AC系统内部错(s"未找到[$v变量名]的第三方名字"))
    Option( v名值对s.get(v第三方名字) match {
      case Some(v) =>
        if (v类型 == classOf[Int]) v.toInt
        else if (v类型 == classOf[Long]) v.toLong
        else if (v类型 == classOf[String]) v
        else if (v类型 == classOf[BigDecimal]) BigDecimal(v)
        else { throw CC系统内部错(s"不支持的数据类型[${v类型.getName}") }
      case None => null
    } )
  }
  def f构建对象(v名值对集s: List[Map[String, String]], v对象类型: Class[_]): Any = {
    val v成员s = v对象类型.getDeclaredFields.toList
    val v成员变量名s = v成员s.map(_.getName)
    val v构建参数s = v对象类型.getDeclaredConstructors.head.getGenericParameterTypes
    // 对case class来说, 成员就是建构方法的构建参数
    def f查泛型类(v: String): Class[_] = {
      val v参数类型 = v构建参数s(v成员变量名s.indexOf(v))
      println(s"$v ==> $v参数类型")
      v参数类型 match {
        case pt: ParameterizedType => pt.getActualTypeArguments.head.asInstanceOf[Class[_]]
        case c: Class[_] => c
      }
    }
    val v成员变量值s = v成员s.map { v成员 =>
      val v成员变量名 = v成员.getName
      v成员.getType match {
        case t: Class[_] if f是元类型_?(t) =>
          f提取变量值(t, v名值对集s.head, v成员变量名).getOrElse(throw CC系统内部错(s"未找到[$v成员变量名]的值"))
        case t: Class[_] if t == classOf[Option[_]] =>
          val v泛型类 = f查泛型类(v成员变量名)
          val x泛型类 = if (v泛型类 != classOf[java.lang.Object]) v泛型类 else
            SerializerUtils.findPrimitiveClass(v对象类型, v成员变量名s, v成员变量名)
          f提取变量值(x泛型类, v名值对集s.head, v成员变量名)
        case t: Class[_] if t == classOf[List[_]] =>
          val v泛型类 = f查泛型类(v成员变量名)
          v名值对集s.tail.map (v名值对s => f构建对象(List(v名值对s), v泛型类) )
        case _ => throw new Error("不支持的类型")
      }
    }
    v对象类型.getConstructors.head.newInstance(v成员变量值s.map(_.asInstanceOf[AnyRef]).toArray: _*)
  }

  val v转义符 = '\\'
  private def f分割首域和其余(data: String, v分割符: Char): (String, String) = {
    var v前字符: Char = ' '
    data.span { b =>
      if (b == v分割符 && v前字符 != v转义符) false else {
        v前字符 = b; true
      }
    }
  }
  private def f拆首域(v域s: ListBuffer[String], data: String): String = {
    val (h, t) = f分割首域和其余(data, '|')
    v域s += h; t.drop(1)
  }
  private def f去转义(data: String): String = new String(data.filter(_ != v转义符))
  private def f拆成名值对(field: String): (String, String) = {
    val (k, v) = f分割首域和其余(field, '=')
    (f去转义(k), f去转义(v.drop(1)))
  }
  def f单层拆报文(v报文: String): Map[String, String] = {
    val v域s = ListBuffer[String]()
    var v剩余报文 = f拆首域(v域s, v报文)
    while (v剩余报文.nonEmpty) {
      v剩余报文 = f拆首域(v域s, v剩余报文)
    }
    v域s.foreach(println)
    v域s.map(f拆成名值对).toMap[String, String]
  }
  private val v分层分割串 = "1:=\\|2:"
  private val v分层串 = "1:=|2:"
  def f拆开报文(v报文: String): List[Map[String, String]] = v报文.split(v分层分割串).map(f单层拆报文).toList
  def f拆报文[A](v报文: String)(implicit mf: scala.reflect.Manifest[A]): A = {
    f构建对象(f拆开报文(v报文), mf.runtimeClass).asInstanceOf[A]
  }
  def f拆报文[A](v名值对集s: List[Map[String, String]])(implicit mf: scala.reflect.Manifest[A]): A = {
    f构建对象(v名值对集s, mf.runtimeClass).asInstanceOf[A]
  }

  private def f组层报文(v对象: Any, v层: Int = 0): List[String] = {
    val v成员及值s = v对象.getClass.getDeclaredFields.map { v成员 =>
      v成员.setAccessible (true)
      (v成员, Option(v成员.get(v对象)))
    }
    v成员及值s.filter(_._2.nonEmpty).map(f => (f._1, f._2.get)).map { every =>
      val (v成员, v变量值) = every
      v成员.getType match {
        case t: Class[_] if t == classOf[Option[_]] =>
          val v第三方名字 = v字典.getOrElse(v成员.getName.drop(1), v成员.getName.drop(1)) // throw AC系统内部错(s"未找到[${v成员.getName}]的第三方名字"))
          v变量值.asInstanceOf[Option[_]] match {
            case Some(z变量值) => s"$v第三方名字=$z变量值"
            case None => ""
          }
        case t: Class[_] if t == classOf[List[_]] =>
          if (v层 > 0) throw CC系统内部错("hfPLUS使用的长亮报文目前仅支持2层")
          if (v成员及值s.last._1 != v成员) throw CC系统内部错("hfPLUS使用的长亮报文要求第2层在最后")
          val v构建参数s = v对象.getClass.getDeclaredConstructors.head.getGenericParameterTypes
          val v泛型Type = v构建参数s.last.asInstanceOf[ParameterizedType]
          val v泛型类 = v泛型Type.getActualTypeArguments.head.asInstanceOf[Class[_]]
          val v第2层s = v变量值.asInstanceOf[List[_]].map { v明细 => f组层报文(v明细, v层 + 1).mkString("|") + "|" }
          if (v第2层s.isEmpty) "" else v分层串 + v第2层s.mkString(v分层串)
        case _ =>
          val v第三方名字 = v字典.getOrElse(v成员.getName.drop(1), v成员.getName.drop(1)) // throw AC系统内部错(s"未找到[${v成员.getName}]的第三方名字"))
          s"$v第三方名字=$v变量值"
      }
    }.toList.filter(_.nonEmpty)
  }
  def f组报文[A](v对象: A): String = {
    val v报文 = f组层报文(v对象).mkString("|")
    if (v报文.last != '|') v报文 + "|" else v报文
  }

}
